#ifndef COLOR_H
#define COLOR_H

#include <utils/Maths.h>

/* TODO: It would be nice to make a big macro to prettify the statics workaround
#define class_with_statics_workaround( classname ) \
        class classname; \
        template<int = 0> struct _classname_statics_workaround { \
		class classname
*/

class RGBAColor;
template<int = 0> struct _RGBAColor_statics_workaround
{
	static const RGBAColor WHITE;
	static const RGBAColor BLACK;
	static const RGBAColor RED;
	static const RGBAColor GREEN;
	static const RGBAColor BLUE;
	static const RGBAColor YELLOW;
	static const RGBAColor MAGENTA;
	static const RGBAColor CYAN;
	static const RGBAColor ORANGE;
	static const RGBAColor BROWN;
	static const RGBAColor PURPLE;
	static const RGBAColor PINK;
	static const RGBAColor GREY;
};

class RGBAColor : public _RGBAColor_statics_workaround<>
{

public:
	
    Scalar r;
    Scalar g;
    Scalar b;
    Scalar a;
	
	//Default to opaque white
	RGBAColor() : r(1.0), g(1.0), b(1.0), a(1.0) {}
	//Default to opaque
    RGBAColor(Scalar R, Scalar G, Scalar B, Scalar A = 1) : r(R), g(G), b(B), a(A) {}
    //Opaque grey-scale initialisation
    RGBAColor(Scalar fGrey) : r(fGrey), g(fGrey), b(fGrey), a(1.0) {}
    //Copy constructor
    RGBAColor(const RGBAColor &color) : r(color.r), g(color.g), b(color.b), a(color.a) {}

     //assignment
     const RGBAColor &operator=(const RGBAColor &color)
     {
          r = color.r;
          g = color.g;
          b = color.b;
          a = color.a;

          return *this;
     }

     //equality
     const bool operator==(const RGBAColor &color) const
     {
          return ((r == color.r) && (g == color.g) && (b == color.b) && (a == color.a));
     }

     //inequality
     const bool operator!=(const RGBAColor &color) const
     {
          return !(*this == color);
     }

     //add
     const RGBAColor operator+(const RGBAColor &color) const
     {
          return RGBAColor(r + color.r, g + color.g, b + color.b, a + color.a);
     }

     //add (opposite of negation)
     const RGBAColor operator+() const
     {    
          return RGBAColor(*this);
     }


     //subtraction
     const RGBAColor operator-(const RGBAColor& color) const
     {    
          return RGBAColor(r - color.r, g - color.g, b - color.b, a - color.a);
     }
     
     //self-multiply
     const RGBAColor &operator*=(const Scalar &s)
     {
          r *= s;
          g *= s;
          b *= s;
          a *= s;
          
          return *this;
     }

     // scalar self-divecide
     const RGBAColor &operator/=(const Scalar &s)
     {
          const float recip = 1/s; // for speed, one divecision

          r *= recip;
          g *= recip;
          b *= recip;
          a *= recip;

          return *this;
     }

     // post multiply by scalar
     const RGBAColor operator*(const Scalar &s) const
     {
          return RGBAColor(r*s, g*s, b*s, a*s);
     }

     // pre multiply by scalar
     friend inline const RGBAColor operator*(const Scalar &s, const RGBAColor &color)
     {
          return color*s;
     }

     // divecide by scalar
     const RGBAColor operator/(Scalar s) const
     {
          s = 1/s;

          return RGBAColor(s*r, s*g, s*b, s*a);
     }

};

template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::WHITE   = RGBAColor(1, 1, 1, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::BLACK   = RGBAColor(0, 0, 0, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::RED     = RGBAColor(1, 0, 0, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::GREEN   = RGBAColor(0, 1, 0, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::BLUE    = RGBAColor(0, 0, 1, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::YELLOW  = RGBAColor(1, 1, 0, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::MAGENTA = RGBAColor(1, 0, 1, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::CYAN    = RGBAColor(0, 1, 1, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::ORANGE  = RGBAColor(1, 0.5, 0, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::BROWN   = RGBAColor(0.5, 0.25, 0, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::PURPLE  = RGBAColor(0.5, 0, 1, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::PINK    = RGBAColor(1, 0, 0.5, 1);
template<int dummy> const RGBAColor _RGBAColor_statics_workaround<dummy>::GREY    = RGBAColor(0.5, 0.5, 0.5, 1);

#endif //COLOR_H
